/*
 * HDRResponseFunctionCalculatorFrame.java
 *
 * Created on 10. November 2008, 11:30
 */
package hdr_plugin;

import hdr_plugin.calibration.ZMatrix.RandomZMatrixBuilder;
import hdr_plugin.response.DebevecCalculator;
import hdr_plugin.response.ResponseFunctionCalculatorSettings;
import hdr_plugin.helper.ImageJTools;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.text.TextWindow;

/**
 *
 * @author Alexander Heidrich
 */
public class HDRResponseFunctionSetupFrame extends java.awt.Frame {

    /** Creates new form HDRResponseFunctionCalculatorFrame */
    public HDRResponseFunctionSetupFrame() {
        initComponents();
        initStackList();
    }

    private void initStackList() {
        chcStack.add("Please Select ...");
        int[] imgList = WindowManager.getIDList();
        String[] imgTitles = new String[imgList.length];
        for (int i = 0; i < imgList.length; i++) {
            ImagePlus imp = WindowManager.getImage(imgList[i]);
            if (imp != null) {
                imgTitles[i] = imp.getTitle();
            } else {
                imgTitles[i] = "";
            }
        }
        for (String title : imgTitles) {
            chcStack.add(title);
        }
        chcStack.select(0);
    }

    private void calcPixels() {
        try {
            int noOfImagesP = Integer.parseInt(txtNoOfImages.getText());
            int Zmin = Integer.parseInt(txtZmin.getText());
            int Zmax = Integer.parseInt(txtZmax.getText());
            Integer pix = ((Zmax - Zmin) / (noOfImagesP - 1)) + 1;
            if (pix < 0) {
                return;
            }
            txtNoOfPixels.setText(pix.toString());
        } catch (Exception e) {
            return;
        }
    }

    private boolean validateInput() {
        return true;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        lblLogo = new javax.swing.JLabel();
        pnlButtons = new java.awt.Panel();
        btnCalcResp = new java.awt.Button();
        bntCancel = new java.awt.Button();
        bntHelp = new java.awt.Button();
        pnlContent = new java.awt.Panel();
        lblStack = new java.awt.Label();
        chcStack = new java.awt.Choice();
        lblImageNo = new java.awt.Label();
        txtNoOfImages = new java.awt.TextField();
        lblPixelNo = new java.awt.Label();
        lblZmin = new java.awt.Label();
        lblExpTimes = new java.awt.Label();
        txtExpTimes = new java.awt.TextField();
        txtZmin = new java.awt.TextField();
        txtZmax = new java.awt.TextField();
        txtNoOfPixels = new java.awt.TextField();
        lblZmax = new java.awt.Label();
        label1 = new java.awt.Label();
        checkbox1 = new java.awt.Checkbox();
        checkbox2 = new java.awt.Checkbox();

        setBackground(new java.awt.Color(255, 255, 255));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });
        setLayout(new java.awt.GridBagLayout());

        lblLogo.setIcon(new javax.swing.ImageIcon("/Users/Alex/Documents/Arbeit/HKI/ProgProj/HDR_Plugin/src/hdr_plugin/resources/log.jpg")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 0);
        add(lblLogo, gridBagConstraints);

        pnlButtons.setLayout(new java.awt.GridBagLayout());

        btnCalcResp.setLabel("Calculate Response Function");
        btnCalcResp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCalcRespActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlButtons.add(btnCalcResp, gridBagConstraints);

        bntCancel.setLabel("Cancel");
        bntCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bntCancelActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlButtons.add(bntCancel, gridBagConstraints);

        bntHelp.setFont(new java.awt.Font("Lucida Grande", 1, 13));
        bntHelp.setLabel("Help");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        pnlButtons.add(bntHelp, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        add(pnlButtons, gridBagConstraints);

        pnlContent.setLayout(new java.awt.GridBagLayout());

        lblStack.setText("HDR Stack:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblStack, gridBagConstraints);

        chcStack.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                chcStackItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(chcStack, gridBagConstraints);

        lblImageNo.setText("No. of Images to Combine (P):");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblImageNo, gridBagConstraints);

        txtNoOfImages.setText("2");
        txtNoOfImages.addTextListener(new java.awt.event.TextListener() {
            public void textValueChanged(java.awt.event.TextEvent evt) {
                txtNoOfImagesTextValueChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(txtNoOfImages, gridBagConstraints);

        lblPixelNo.setText("Number of needed Pixels (N)");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblPixelNo, gridBagConstraints);

        lblZmin.setText("Min. Pixel Value (Zmin):");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblZmin, gridBagConstraints);
        lblZmin.getAccessibleContext().setAccessibleName("Min Pixel Value:");

        lblExpTimes.setText("List of Exposure Times:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblExpTimes, gridBagConstraints);

        txtExpTimes.addTextListener(new java.awt.event.TextListener() {
            public void textValueChanged(java.awt.event.TextEvent evt) {
                test(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 200;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(txtExpTimes, gridBagConstraints);

        txtZmin.setText("0");
        txtZmin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtZminActionPerformed(evt);
            }
        });
        txtZmin.addTextListener(new java.awt.event.TextListener() {
            public void textValueChanged(java.awt.event.TextEvent evt) {
                txtZminTextValueChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(txtZmin, gridBagConstraints);

        txtZmax.setText("0");
        txtZmax.addTextListener(new java.awt.event.TextListener() {
            public void textValueChanged(java.awt.event.TextEvent evt) {
                txtZmaxTextValueChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(txtZmax, gridBagConstraints);

        txtNoOfPixels.setEditable(false);
        txtNoOfPixels.setEnabled(false);
        txtNoOfPixels.setText("1");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(txtNoOfPixels, gridBagConstraints);

        lblZmax.setText("Max. Pixel Value (Zmax):");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlContent.add(lblZmax, gridBagConstraints);

        label1.setText("Image Type:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        pnlContent.add(label1, gridBagConstraints);

        checkbox1.setEnabled(false);
        checkbox1.setLabel("16 bit");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        pnlContent.add(checkbox1, gridBagConstraints);

        checkbox2.setEnabled(false);
        checkbox2.setLabel("RGB");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 5;
        pnlContent.add(checkbox2, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(6, 5, 0, 5);
        add(pnlContent, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        this.dispose();
    }//GEN-LAST:event_exitForm

    private void btnCalcRespActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCalcRespActionPerformed
        // check if user has selected a stack
        if (chcStack.getSelectedIndex() == 0) {
            IJ.error("Please select a stack to work with!");
            return;
        }

        // check if the user has entered exposure times
        if (txtExpTimes.getText().equals("")) {
            IJ.error("Please enter exposure times!");
            return;
        }

        try {
        // get the selected stack from ImageJ
        ImagePlus imp = WindowManager.getImage(chcStack.getSelectedItem());

        // get number of pixels, number of images to combine, lowest and highest
        // pixel value (if applicable) from text fields
        int noOfImagesP = Integer.parseInt(txtNoOfImages.getText());
        int noOfPixelsN = Integer.parseInt(txtNoOfPixels.getText());
        int Zmin = Integer.parseInt(txtZmin.getText());
        int Zmax = Integer.parseInt(txtZmax.getText());

        // get the exposure values as string and split this string at every
        // comma to store the single exposure times in a double array
        String[] values = txtExpTimes.getText().split(",");
        double[] expTimes = new double[values.length];
        for (int i = 0; i < expTimes.length; i++) {
            expTimes[i] = new Double(values[i].trim().replaceAll(" ", ""));
        }

        if (noOfImagesP == 0) {
            IJ.error("Please select an appropriate number of images for the calculation of the camera response function");
            return;
        }

        if (noOfPixelsN == 0) {
            return;
        }

        if (noOfImagesP > imp.getStackSize()) {
            IJ.error("The number of images P is higher than the number of available images in the selected image stack!");
            return;
        }

        if (imp.getStackSize() < 2) {
            IJ.error("The size of the selected image stack is too small. You need at least two images for the calculation of the camera response function!");
            return;
        }

        if (!(noOfImagesP == expTimes.length)) {
            IJ.error("Exposure Times Missing!","The number of images P is higher than the number of given exposure times!");
            return;
        }

        if (Zmin > Zmax) {
            IJ.error("Zmin is higher than Zmax!");
            return;
        }

        // get image pixel, convert to int and split up into single channels
        // the structure of the array is
        // imgPixels[channel][pixel][image]
        System.out.println("start convert");
        //int[][][] imgPixels = ImageJTools.checkAndConvert(imp);
        System.out.println("end convert");


        int arrayWidth = imp.getStack().getWidth();
        int arrayHeight = imp.getStack().getHeight();

        ResponseFunctionCalculatorSettings settings = new ResponseFunctionCalculatorSettings();
        settings.setExpTimes(expTimes);
        settings.setNoOfChannels(imp.getNChannels());
        settings.setNoOfImagesP(noOfImagesP);
        settings.setNoOfPixelsN(noOfPixelsN);
        settings.setZmax(Zmax);
        settings.setZmin(Zmin);
        settings.setHeight(imp.getStack().getHeight());
        settings.setWidth(imp.getStack().getWidth());

        // select random pixel values as given by the user
        int[][][] rndPixels = new RandomZMatrixBuilder(imp, noOfPixelsN, noOfImagesP).getZ();

        DebevecCalculator responseFunc = new DebevecCalculator(rndPixels, settings);
        
        HDRResponseFunctionCalculatorFrame gui = new HDRResponseFunctionCalculatorFrame(responseFunc);
        gui.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
            new TextWindow("Error!", e.getMessage() + "An error occured while processing your input. Please make sure that you entered all information in the correct (numerical) format.", 400, 400).setVisible(true);
            return;
        }
}//GEN-LAST:event_btnCalcRespActionPerformed

    private void txtZminActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtZminActionPerformed
        // TODO add your handling code here:
}//GEN-LAST:event_txtZminActionPerformed

    private void chcStackItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chcStackItemStateChanged
    }//GEN-LAST:event_chcStackItemStateChanged

    private void txtNoOfImagesTextValueChanged(java.awt.event.TextEvent evt) {//GEN-FIRST:event_txtNoOfImagesTextValueChanged
        calcPixels();
}//GEN-LAST:event_txtNoOfImagesTextValueChanged

    private void txtZminTextValueChanged(java.awt.event.TextEvent evt) {//GEN-FIRST:event_txtZminTextValueChanged
        calcPixels();
    }//GEN-LAST:event_txtZminTextValueChanged

    private void txtZmaxTextValueChanged(java.awt.event.TextEvent evt) {//GEN-FIRST:event_txtZmaxTextValueChanged
        calcPixels();
    }//GEN-LAST:event_txtZmaxTextValueChanged

    private void bntCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bntCancelActionPerformed
        this.dispose();
    }//GEN-LAST:event_bntCancelActionPerformed

    private void test(java.awt.event.TextEvent evt) {//GEN-FIRST:event_test
        // TODO add your handling code here:
    }//GEN-LAST:event_test

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new HDRResponseFunctionSetupFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private java.awt.Button bntCancel;
    private java.awt.Button bntHelp;
    private java.awt.Button btnCalcResp;
    private java.awt.Choice chcStack;
    private java.awt.Checkbox checkbox1;
    private java.awt.Checkbox checkbox2;
    private java.awt.Label label1;
    private java.awt.Label lblExpTimes;
    private java.awt.Label lblImageNo;
    private javax.swing.JLabel lblLogo;
    private java.awt.Label lblPixelNo;
    private java.awt.Label lblStack;
    private java.awt.Label lblZmax;
    private java.awt.Label lblZmin;
    private java.awt.Panel pnlButtons;
    private java.awt.Panel pnlContent;
    private java.awt.TextField txtExpTimes;
    private java.awt.TextField txtNoOfImages;
    private java.awt.TextField txtNoOfPixels;
    private java.awt.TextField txtZmax;
    private java.awt.TextField txtZmin;
    // End of variables declaration//GEN-END:variables
}
